/*
 * NOutputGate.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;

import java.util.*;
import java.io.*;
import middle.*;

/**
 * guess..
 */

class NOutputGate extends StdGate implements Monitor, Executable{

	BitVector lastInput, lastOutput;
	Expression input;
	LeftValue outputs;
	int length;

	NOutputGate(NameSpace parent, Delay3 delay, 
			ModuleInstanceDescription id, byte type) throws ParseException
			{
		this(parent, delay, null, null, id, type);
			}

	NOutputGate(NameSpace parent, Delay3 delay, 
			LeftValue outputs, Expression input,
			ModuleInstanceDescription id, byte type) throws ParseException
			{
		super(parent, delay, type, id);
		this.outputs = outputs;
		this.input = input;
		input.addMonitor(this);
		try {
			lastInput = input.evaluate().getBits();
		} catch (InterpretTimeException itex) {
			throw new ParseException (itex.toString());
		}

		lastOutput = BitVector.bZ();
		length = outputs.length();
			}

	public void trigger()throws InterpretTimeException {

		BitVector curInput = input.evaluate().getBits();
		xConsole.debug("NOutputGate: trigger: lastVal: " + lastInput +
				" curinput: " + curInput);
		if (curInput.equals(lastInput)) return;
		lastInput = curInput;
		xConsole.debug("length: " + length + "output: " +
				truthTables[type][curInput.getBit(curInput.msb)] +
				" input: " + curInput.getBit(curInput.msb));
		BitVector curOutput =
			new BitVector((byte) truthTables[type][curInput.getBit(curInput.msb)],
					length);
		xConsole.debug("curOutput: " + curOutput);
		if (curOutput.equals(lastOutput)) return;
		int iDelay = Wire.computeTransitionDelayFor(lastOutput, curOutput, delay);
		lastOutput = curOutput;
		lastUpdateTime = Time.oClock() + iDelay;
		Time.addFinisher(iDelay, new GenericInstruction(this));
	}

	public void execute ()
	throws InterpretTimeException
	{
		if (lastUpdateTime < Time.oClock()) return; //not now
		xConsole.trace(this + ": " + outputs + " <<< " + lastOutput);
		outputs.assign(lastOutput);
	}

}



